package thread.safe;

import java.time.LocalDateTime;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;

/**
 * @author bc
 * @Description:
 * @date 2024/03/11
 */
@SuppressWarnings("ALL")
public class DemoTest {
    static volatile int semaphore = 1;

    public static void main(String[] args) throws Exception{

        sameTimeRun();
//        orderRun();
//        orderByVolatile();
//        orderInterlace();
    }

    //三个线程同时执行
    private static void sameTimeRun() throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(2);
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
//                System.out.println("线程" + Thread.currentThread().getName() + "执行开始" + LocalDateTime.now());
                try {
                    countDownLatch.await();
                    //业务逻辑
                    System.err.println("线程" + Thread.currentThread().getName() + "执行" + LocalDateTime.now());
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
//                System.out.println("线程:" + Thread.currentThread().getName() + "执行结束" + LocalDateTime.now());
            }).start();
        }

        Thread.sleep(1000);
        countDownLatch.countDown();
        System.out.println("1");
        Thread.sleep(5000);
        countDownLatch.countDown();
    }

    //三个线程依次执行
    private static void orderRun() throws Exception {
        Semaphore semaphore = new Semaphore(1);
        Thread t1 = new Thread(() -> {
            try {
                semaphore.acquire();
                for (int i = 0; i < 10; i++) {
                    System.out.println("A:" + i);
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                semaphore.release();
            }
        });

        Thread t2 = new Thread(() -> {
            try {
                semaphore.acquire();
                for (int i = 0; i < 10; i++) {
                    System.out.println("B:" + i);
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                semaphore.release();
            }
        });

        Thread t3 = new Thread(() -> {
            try {
                semaphore.acquire();
                for (int i = 0; i < 10; i++) {
                    System.out.println("C:" + i);
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                semaphore.release();
            }
        });

        t2.start();
        t1.start();
        t3.start();
    }

    //通过volatile关键字来实现依次执行
    private static void orderByVolatile() throws Exception {
        Thread t1 = new Thread(() -> {
            while(true) {
                if (semaphore == 1) {
                    for (int i = 0; i < 10; i++) {
                        System.out.println("A:" + i);
                    }
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    semaphore = 2;
                    return;
                }
            }
        });

        Thread t2 = new Thread(() -> {
            while(true) {
                if (semaphore == 2) {
                    for (int i = 0; i < 10; i++) {
                        System.out.println("B:" + i);
                    }
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    semaphore = 3;
                    return;
                }
            }
        });

        Thread t3= new Thread(() -> {
            while(true) {
                if (semaphore == 3) {
                    for (int i = 0; i < 10; i++) {
                        System.out.println("C:" + i);
                    }
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    semaphore = 1;
                    return;
                }
            }
        });

        t1.start();
        t2.start();
        t3.start();
    }

    //三个线程有序交错执行
    private static void orderInterlace() throws InterruptedException {
        Semaphore s1 = new Semaphore(1);
        Semaphore s2 = new Semaphore(1);
        Semaphore s3 = new Semaphore(1);

        s1.acquire();
        s2.acquire();


        Thread t1 = new Thread(() -> {
            while(true) {
                try {
                    s1.acquire();
                    System.out.println(Thread.currentThread().getName() + "A");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } finally {
                    s2.release();
                }
            }
        });

        Thread t2 = new Thread(() -> {
            while(true) {
                try {
                    s2.acquire();
                    System.out.println(Thread.currentThread().getName() + "B");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } finally {
                    s3.release();
                }
            }
        });

        Thread t3 = new Thread(() -> {
            while(true){
                try {
                    s3.acquire();
                    System.out.println(Thread.currentThread().getName() + "C");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } finally {
                    s1.release();
                }
            }
        });

        t1.start();
        t2.start();
        t3.start();
    }
}
